﻿//Created by Action Script Viewer - http://www.buraks.com/asv
package Engine.Managers {
    import Engine.Interfaces.*;
    import flash.utils.*;
    import __AS3__.vec.*;

    public class ProcessManager {

        public static const TICKS_PER_SECOND:int = 30;
        public static const TICK_RATE:Number = (1 / Number(TICKS_PER_SECOND));
        public static const TICK_RATE_MS:Number = (TICK_RATE * 1000);
        public static const MAX_TICKS_PER_FRAME:int = 5;

        private static var m_instance:ProcessManager = null;
        private static var m_canInstantiate:Boolean = false;

        private var m_timeScale:Number = 1;
        private var m_virtualTime:int = 0;
        private var m_platformTime:int = 0;
        private var m_lastTime:int = -1;
        private var m_elapsed:Number = 0;
        private var m_needPurgeEmpty:Boolean = false;
        private var m_processing:Boolean = false;
        private var m_active:Boolean = false;
        private var m_framedObjects:Vector.<FramedProcessObject>;
        private var m_tickedObjects:Vector.<TickedProcessObject>;
        private var m_deferredFramedObjects:Vector.<FramedProcessObject>;
        private var m_deferredTickedObjects:Vector.<TickedProcessObject>;

        public function ProcessManager(){
            this.m_framedObjects = new Vector.<FramedProcessObject>();
            this.m_tickedObjects = new Vector.<TickedProcessObject>();
            this.m_deferredFramedObjects = new Vector.<FramedProcessObject>();
            this.m_deferredTickedObjects = new Vector.<TickedProcessObject>();
            super();
            if (!m_canInstantiate){
                throw (new Error("Cannot call ProcessManager constructor directly - use ProcessManager.instance instead."));
            };
        }
        public static function get instance():ProcessManager{
            if (null == m_instance){
                m_canInstantiate = true;
                m_instance = new (ProcessManager)();
                m_canInstantiate = false;
            };
            return (m_instance);
        }

        public function get timeScale():Number{
            return (this.m_timeScale);
        }
        public function set timeScale(_arg1:Number):void{
            this.m_timeScale = _arg1;
        }
        public function get virtualTime():Number{
            return (this.m_virtualTime);
        }
        public function get platformTime():Number{
            return (this.m_platformTime);
        }
        public function activate():void{
            if (!this.m_active){
                this.m_lastTime = -1;
                this.m_elapsed = 0;
                this.m_active = true;
            };
        }
        public function deactivate():void{
            if (this.m_active){
                this.m_active = false;
            };
        }
        public function get isActive():Boolean{
            return (this.m_active);
        }
        public function addFramedObject(_arg1:IFramedObject, _arg2:Number=0):void{
            var _local3:FramedProcessObject = new FramedProcessObject();
            _local3.object = _arg1;
            _local3.priority = _arg2;
            this.pushFramedObject(_local3);
        }
        public function addTickedObject(_arg1:ITickedObject, _arg2:Number=0):void{
            var _local3:TickedProcessObject = new TickedProcessObject();
            _local3.object = _arg1;
            _local3.priority = _arg2;
            this.pushTickedObject(_local3);
        }
        public function removeFramedObject(_arg1:IFramedObject):void{
            if (this.objectCount == 1){
                this.deactivate();
            };
            var _local2:int;
            while (_local2 < this.m_framedObjects.length) {
                if (((this.m_framedObjects[_local2]) && ((this.m_framedObjects[_local2].object == _arg1)))){
                    if (this.m_processing){
                        this.m_framedObjects[_local2] = null;
                        this.m_needPurgeEmpty = true;
                    } else {
                        this.m_framedObjects.splice(_local2, 1);
                    };
                    if (0 == this.m_framedObjects.length){
                        this.m_framedObjects = new Vector.<FramedProcessObject>();
                    };
                    break;
                };
                _local2++;
            };
        }
        public function removeTickedObject(_arg1:ITickedObject):void{
            if (this.objectCount == 1){
                this.deactivate();
            };
            var _local2:int;
            while (_local2 < this.m_tickedObjects.length) {
                if (((this.m_tickedObjects[_local2]) && ((this.m_tickedObjects[_local2].object == _arg1)))){
                    if (this.m_processing){
                        this.m_tickedObjects[_local2] = null;
                        this.m_needPurgeEmpty = true;
                    } else {
                        this.m_tickedObjects.splice(_local2, 1);
                    };
                    if (0 == this.m_tickedObjects.length){
                        this.m_tickedObjects = new Vector.<TickedProcessObject>();
                    };
                    break;
                };
                _local2++;
            };
        }
        public function onFrame():void{
            var _local1:Number;
            var _local2:Number;
            if (this.m_active){
                _local1 = getTimer();
                if (this.m_lastTime >= 0){
                    _local2 = (Number((_local1 - this.m_lastTime)) * this.m_timeScale);
                    this.process(_local2);
                };
                this.m_lastTime = _local1;
            };
        }
        private function get objectCount():int{
            return ((this.m_tickedObjects.length + this.m_framedObjects.length));
        }
        private function pushFramedObject(_arg1:FramedProcessObject):void{
            var _local2:int;
            var _local3:int;
            if (this.m_processing){
                this.m_deferredFramedObjects.push(_arg1);
            } else {
                if (!this.m_active){
                    this.activate();
                };
                if (-1 == this.m_framedObjects.indexOf(_arg1)){
                    _local2 = -1;
                    _local3 = 0;
                    while (_local3 < this.m_framedObjects.length) {
                        if (((this.m_framedObjects[_local3]) && ((this.m_framedObjects[_local3].priority < _arg1.priority)))){
                            _local2 = _local3;
                            break;
                        };
                        _local3++;
                    };
                    if ((((_local2 < 0)) || ((_local2 >= this.m_framedObjects.length)))){
                        this.m_framedObjects.push(_arg1);
                    } else {
                        this.m_framedObjects.splice(_local2, 0, _arg1);
                    };
                };
            };
        }
        private function pushTickedObject(_arg1:TickedProcessObject):void{
            var _local2:int;
            var _local3:int;
            if (this.m_processing){
                this.m_deferredTickedObjects.push(_arg1);
            } else {
                if (!this.m_active){
                    this.activate();
                };
                if (-1 == this.m_tickedObjects.indexOf(_arg1)){
                    _local2 = -1;
                    _local3 = 0;
                    while (_local3 < this.m_tickedObjects.length) {
                        if (((this.m_tickedObjects[_local3]) && ((this.m_tickedObjects[_local3].priority < _arg1.priority)))){
                            _local2 = _local3;
                            break;
                        };
                        _local3++;
                    };
                    if ((((_local2 < 0)) || ((_local2 >= this.m_tickedObjects.length)))){
                        this.m_tickedObjects.push(_arg1);
                    } else {
                        this.m_tickedObjects.splice(_local2, 0, _arg1);
                    };
                };
            };
        }
        private function process(_arg1:Number):void{
            var _local2:uint;
            var _local4:TickedProcessObject;
            var _local6:FramedProcessObject;
            var _local7:int;
            this.m_platformTime = getTimer();
            this.m_elapsed = (this.m_elapsed + _arg1);
            var _local3:int;
            while ((((this.m_elapsed >= TICK_RATE_MS)) && ((_local3 < MAX_TICKS_PER_FRAME)))) {
                this.processDeferredObjects();
                this.m_processing = true;
                _local2 = 0;
                while (_local2 < this.m_tickedObjects.length) {
                    _local4 = this.m_tickedObjects[_local2];
                    if (_local4){
                        _local4.object.onTick(TICK_RATE);
                    };
                    _local2++;
                };
                this.m_processing = false;
                this.m_virtualTime = (this.m_virtualTime + TICK_RATE_MS);
                this.m_elapsed = (this.m_elapsed - TICK_RATE_MS);
                _local3++;
            };
            if (_local3 >= MAX_TICKS_PER_FRAME){
                _local7 = (this.m_elapsed / TICK_RATE_MS);
                this.m_elapsed = (this.m_elapsed - (TICK_RATE_MS * _local7));
            };
            this.m_processing = true;
            var _local5:Number = (_arg1 / 1000);
            _local2 = 0;
            while (_local2 < this.m_framedObjects.length) {
                _local6 = this.m_framedObjects[_local2];
                if (_local6){
                    _local6.object.onFrame(_local5);
                };
                _local2++;
            };
            this.m_processing = false;
            if (this.m_needPurgeEmpty){
                this.purgeEmpty();
            };
        }
        private function processDeferredObjects():void{
            var _local1:uint;
            var _local2:Vector.<FramedProcessObject> = this.m_deferredFramedObjects;
            if (0 < _local2.length){
                this.m_deferredFramedObjects = new Vector.<FramedProcessObject>();
                _local1 = 0;
                while (_local1 < _local2.length) {
                    this.pushFramedObject(_local2[_local1]);
                    _local1++;
                };
            };
            var _local3:Vector.<TickedProcessObject> = this.m_deferredTickedObjects;
            if (0 < _local3.length){
                this.m_deferredTickedObjects = new Vector.<TickedProcessObject>();
                _local1 = 0;
                while (_local1 < _local3.length) {
                    this.pushTickedObject(_local3[_local1]);
                    _local1++;
                };
            };
        }
        private function purgeEmpty():void{
            var _local1:uint;
            _local1 = 0;
            while (_local1 < this.m_framedObjects.length) {
                if (!this.m_framedObjects[_local1]){
                    this.m_framedObjects.splice(_local1, 1);
                    _local1--;
                };
                _local1++;
            };
            _local1 = 0;
            while (_local1 < this.m_tickedObjects.length) {
                if (!this.m_tickedObjects[_local1]){
                    this.m_tickedObjects.splice(_local1, 1);
                    _local1--;
                };
                _local1++;
            };
            if (0 == this.m_framedObjects.length){
                this.m_framedObjects = new Vector.<FramedProcessObject>();
            };
            if (0 == this.m_tickedObjects.length){
                this.m_tickedObjects = new Vector.<TickedProcessObject>();
            };
            this.m_needPurgeEmpty = false;
        }

    }
}//package Engine.Managers 

import Engine.Interfaces.*;

final class FramedProcessObject {

    public var object:IFramedObject = null;
    public var priority:Number = 0;

    public function FramedProcessObject(){
    }
}
final class TickedProcessObject {

    public var object:ITickedObject = null;
    public var priority:Number = 0;

    public function TickedProcessObject(){
    }
}
